package cloud

import (
	"encoding/base64"
	"os"
	"strings"
	"time"
	"tinyGW/app/models"
	"tinyGW/pkg/plugin/io"
	"tinyGW/pkg/service/event"
	"tinyGW/pkg/util"

	"github.com/gookit/color"
	"github.com/mitchellh/mapstructure"
	"go.uber.org/zap"
)

// 处理网关操作 网关重启(reboot)、远程升级(upgrade)
// 获取表具设备(getdevice)、下发表具设备(setdevice)、PING(ping)
const (
	GETLOG              = "GetLog"
	GETDEVICETYPE       = "GetDeviceType"
	GETCOLLECTORS       = "GetCollectors"
	SETCOLLECTORS       = "SetCollectors"
	SETINSTRUMENTS      = "SetInstruments"
	SETINSTRUMENTTYPES  = "SetInstrumentTypes"
	SETINSTRUMENTDRIVER = "SetInstrumentDriver"
	GetCollectTask      = "GetCollectTask"
	SetCollectTask      = "SetCollectTask"
	//------------------------------------------
	REBOOT  = "Reboot"
	UPGRADE = "Upgrade"
	PING    = "Ping"
	//------------------------------------------
	HEALTHCHECK = "HealthCheck"
	ReadReal    = "ReadReal"
)

type commandExecutor func(params map[string]interface{}, client Client) (int, interface{})

var (
	GatewayCommand map[string]commandExecutor = initGatewayCommand()
)

func initGatewayCommand() map[string]commandExecutor {
	result := make(map[string]commandExecutor)
	result[GETDEVICETYPE] = getDeviceType
	result[GETCOLLECTORS] = getCollectors
	result[SETCOLLECTORS] = setCollectors
	result[SETINSTRUMENTS] = setInstruments
	result[SETINSTRUMENTTYPES] = setInstrumentTypes
	result[SETINSTRUMENTDRIVER] = setInstrumentDriver
	result[GetCollectTask] = getCollectTask
	result[SetCollectTask] = setCollectTask
	//------------------------------------------------------
	result[GETLOG] = getLog
	result[REBOOT] = reboot
	result[UPGRADE] = upgrade
	result[PING] = ping
	result[HEALTHCHECK] = healthCheck
	result[ReadReal] = readReal

	//http.Handle("/metrics", promhttp.Handler())

	return result
}

func readReal(params map[string]interface{}, client Client) (int, interface{}) {
	devices, err := client.deviceRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC获取设备失败, ERROR: %v", err)
		return 1, nil
	}
	key := "read_real"
	_, is := client.cache.Get(key)
	if is {
		return 1, "任务正在执行中！"
	}
	count := len(devices)
	client.eventBus.Publish(event.Event{Name: "ReadReal", Data: count})
	client.cache.Set(key, "running", time.Duration(count*2)*time.Second)
	return 0, "任务开始执行！"
}

func getCollectTask(params map[string]interface{}, client Client) (int, interface{}) {
	collectTask, err := client.collectTaskRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC获取采集任务失败, ERROR: %v", err)
		return 1, nil
	}
	return 0, collectTask
}

func setCollectTask(params map[string]interface{}, client Client) (int, interface{}) {
	collectTasks, ok := params["collectTask"].([]interface{})
	if !ok {
		zap.S().Errorf("RPC设置采集任务失败: 参数collectTask类型不正确")
		return 1, nil
	}
	for _, value := range collectTasks {
		collectTask, ok := value.(map[string]interface{})
		if !ok {
			color.Redln("RPC设置采集任务失败: 参数collectTask类型不正确")
			return 1, nil
		}
		ct := models.CollectTask{}
		err := mapstructure.Decode(collectTask, &ct)
		if err != nil {
			color.Redln("RPC设置采集任务失败: 参数collectTask类型转换失败", err.Error())
			return 1, nil
		}
		err = client.collectTaskRepository.Save(&ct)
		if err != nil {
			color.Redln("RPC设置采集任务失败: 保存采集任务时发生错误, ERROR: %v", err)
			return 1, nil
		}
	}
	return 0, nil
}

func setInstrumentDriver(params map[string]interface{}, client Client) (int, interface{}) {
	var err error
	instrument, ok := params["instrument"].(string)
	if !ok {
		zap.S().Errorf("RPC设置采集器失败: 参数instrument类型不正确")
		return 1, nil
	}
	driver, ok := params["driver"].(string)
	if !ok {
		zap.S().Errorf("RPC设置采集器失败: 参数driver类型不正确")
		return 1, nil
	}
	color.Greenln("RPC设置采集器:", instrument, driver)
	driverName, ok := params["driverName"].(string)
	find, err := client.deviceTypeRepository.Find(instrument)
	if err != nil {
		color.Redln("RPC设置采集器失败: 参数collectors类型不正确-")
		return 1, nil
	}
	color.Greenln(find.Driver)
	sDec, _ := base64.StdEncoding.DecodeString(driver)
	// 写到文件
	err = io.WriteFile("/plugin/"+driverName, sDec)
	if err != nil {
		color.Redln("RPC设置采集器失败: 写入驱动文件时发生错误", err.Error())
		return 1, nil
	}
	dir := io.GetPluginPath() + driverName
	err = io.Unzip(dir, io.GetPluginPath())
	if err != nil {
		color.Redln("RPC设置采集器失败: 解压驱动文件时发生错误", err.Error())
		return 1, nil
	}
	err = os.Remove(dir)
	if err != nil {
		color.Redln("RPC设置采集器失败: 删除驱动文件时发生错误", err.Error())
		return 0, nil
	}
	dn := strings.Split(driverName, ".")
	color.Greenln("RPC设置采集器:", dn[0], driverName)
	find.Driver = dn[0]
	err = client.deviceTypeRepository.Save(&find)
	if err != nil {
		color.Redln("RPC设置采集器失败: 保存驱动文件时发生错误", err.Error())
		return 1, nil
	}
	return 0, nil
}

func getInstruments(params map[string]interface{}, client Client) (int, interface{}) {
	all, err := client.deviceRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC获取设备失败, ERROR: %v", err)
		return 1, nil
	}
	return 0, all
}

func setInstruments(params map[string]interface{}, client Client) (int, interface{}) {
	instruments, ok := params["instruments"].([]interface{})
	if !ok {
		zap.S().Errorf("RPC设置仪表失败: 参数instruments类型不正确")
		return 1, nil
	}

	// 获取现有的设备
	existingDevices, err := client.deviceRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC设置仪表失败: 获取仪表列表时发生错误, ERROR: %v", err)
		return 1, nil
	}

	// 构建新设备的名称集合
	newDeviceNames := make(map[string]bool)
	successCount := 0
	for _, v := range instruments {
		instrumentMap, ok := v.(map[string]interface{})
		if !ok {
			color.Redln("RPC设置仪表失败: 参数instruments解析失败")
			return 1, nil
		}
		c, ok := instrumentMap["collector"].(map[string]interface{})
		if !ok {
			color.Redln("RPC设置仪表失败: 采集器参数解析失败")
			return 1, nil
		}

		cn, ok := c["name"].(string)
		if !ok || cn == "" {
			color.Yellowln("RPC设置仪表警告: 跳过采集器名称为空的仪表")
			continue
		}

		//instrumentMap["collectTime"] = time.Now()
		//instrumentMap["ReportTime"] = time.Now()
		var instrument models.Device
		err := mapstructure.Decode(instrumentMap, &instrument)
		if err != nil {
			color.Redln("RPC设置仪表失败: 参数instruments类型转换失败", err.Error())
			return 1, nil
		}

		// 检查设备名称
		if instrument.Name == "" {
			color.Yellowln("RPC设置仪表警告: 跳过名称为空的设备")
			continue
		}

		// 检查设备类型名称
		if instrument.Type.Name == "" {
			color.Yellowln("RPC设置仪表警告: 跳过设备类型为空的仪表, 设备名称:", instrument.Name)
			continue
		}

		newDeviceNames[instrument.Name] = true

		// 查找或创建设备类型
		deviceType, err := client.deviceTypeRepository.Find(instrument.Type.Name)
		if err != nil {
			// 如果找不到，自动创建（支持并发同步）
			var newDeviceType models.DeviceType
			util.ToolUtil.Copy(&newDeviceType, instrument.Type)
			if err := client.deviceTypeRepository.Save(&newDeviceType); err != nil {
				color.Redln("RPC设置仪表失败: 保存设备类型时发生错误, ERROR: %v", err)
				return 1, nil
			}
			deviceType = newDeviceType
			zap.S().Infof("RPC设置仪表: 设备类型 %s 不存在，已自动创建", newDeviceType.Name)
		}
		instrument.Type = deviceType

		// 查找或创建采集器
		collector, err := client.collectorRepository.Find(cn)
		if err != nil {
			// 如果找不到，自动创建（支持并发同步）
			var coll models.Collector
			util.ToolUtil.Copy(&coll, c)

			// 确保采集器名称不为空
			if coll.Name == "" {
				coll.Name = cn
			}

			// 确保采集器类型不为空
			if coll.Type == "" {
				coll.Type = "Serial" // 默认使用Serial类型
			}

			if err := client.collectorRepository.Save(&coll); err != nil {
				color.Redln("RPC设置仪表失败: 保存采集器时发生错误, ERROR: %v", err)
				return 1, nil
			}
			collector = coll
			zap.S().Infof("RPC设置仪表: 采集器 %s 不存在，已自动创建", coll.Name)
		}
		instrument.Collector = collector

		// 保存或更新设备
		if err := client.deviceRepository.Save(&instrument); err != nil {
			color.Redln("RPC设置仪表失败: 保存设备时发生错误, ERROR: %v", err)
			return 1, nil
		}
		successCount++
		color.Greenln("RPC设置仪表成功:", instrument.Name)
	}

	// 删除不在新列表中的旧设备
	for _, existingDevice := range existingDevices {
		if !newDeviceNames[existingDevice.Name] {
			if err := client.deviceRepository.Delete(existingDevice.Name); err != nil {
				zap.S().Warnf("删除旧设备失败: %s, ERROR: %v", existingDevice.Name, err)
			} else {
				color.Yellowln("RPC清理设备:", existingDevice.Name)
			}
		}
	}

	zap.S().Infof("RPC设置仪表完成: 成功保存 %d 个设备", successCount)
	return 0, nil
}

func setInstrumentTypes(params map[string]interface{}, client Client) (int, interface{}) {
	instrumentTypes, ok := params["instrumentTypes"].([]interface{})
	if !ok {
		zap.S().Errorf("RPC设置仪表类型失败: 参数instrumentTypes类型不正确")
		return 1, nil
	}

	// 获取现有的设备类型
	existingTypes, err := client.deviceTypeRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC设置仪表类型失败: 获取仪表类型列表时发生错误, ERROR: %v", err)
		return 1, nil
	}

	// 构建新设备类型的名称集合
	newTypeNames := make(map[string]bool)
	for _, v := range instrumentTypes {
		instrumentMap, ok := v.(map[string]interface{})
		if !ok {
			color.Redln("RPC设置仪表类型失败: 参数解析失败")
			return 1, nil
		}

		var instrument models.DeviceType
		err = mapstructure.Decode(instrumentMap, &instrument)
		if err != nil {
			color.Redln("RPC设置仪表类型失败: 参数类型转换失败", err.Error())
			return 1, nil
		}

		if instrument.Name == "" {
			color.Yellowln("RPC设置仪表类型警告: 跳过名称为空的设备类型")
			continue
		}

		newTypeNames[instrument.Name] = true

		// 保存或更新设备类型
		var deviceType models.DeviceType
		util.ToolUtil.Copy(&deviceType, instrument)
		if err := client.deviceTypeRepository.Save(&deviceType); err != nil {
			color.Redln("RPC设置仪表类型失败: 保存设备类型时发生错误, ERROR: %v", err)
			return 1, nil
		}
		color.Greenln("RPC设置仪表类型成功:", deviceType.Name)
	}

	// 删除不在新列表中的旧设备类型
	for _, existingType := range existingTypes {
		if !newTypeNames[existingType.Name] {
			if err := client.deviceTypeRepository.Delete(existingType.Name); err != nil {
				zap.S().Warnf("删除设备类型失败: %s, ERROR: %v", existingType.Name, err)
			} else {
				color.Yellowln("RPC清理设备类型:", existingType.Name)
			}
		}
	}

	return 0, nil
}

func setCollectors(params map[string]interface{}, client Client) (int, interface{}) {
	collectors, ok := params["collectors"].([]interface{})
	if !ok {
		zap.S().Errorf("RPC设置采集器失败: 参数collectors类型不正确")
		return 1, nil
	}

	// 获取现有的采集器
	existingCollectors, err := client.collectorRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC设置采集器失败: 获取采集器列表时发生错误, ERROR: %v", err)
		return 1, nil
	}

	// 构建新采集器的名称集合
	newCollectorNames := make(map[string]bool)
	for _, collectorInterface := range collectors {
		collector, ok := collectorInterface.(map[string]interface{})
		if !ok {
			zap.S().Errorf("RPC设置采集器失败: collector类型不正确")
			return 1, nil
		}
		var c models.Collector
		if err = mapstructure.Decode(collector, &c); err != nil {
			zap.S().Errorf("RPC设置采集器失败: 解析collector失败, ERROR: %v", err)
			return 1, nil
		}

		// 检查采集器名称是否为空，为空则跳过
		if c.Name == "" {
			zap.S().Warnf("RPC设置采集器: 跳过名称为空的采集器")
			continue
		}

		// 确保采集器类型不为空
		if c.Type == "" {
			c.Type = "Serial" // 默认使用Serial类型
			zap.S().Warnf("RPC设置采集器: 采集器 %s 类型为空，设置为默认类型 Serial", c.Name)
		}

		newCollectorNames[c.Name] = true

		// 保存或更新采集器（事件已禁用，不会影响当前采集任务）
		var newCollector models.Collector
		util.ToolUtil.Copy(&newCollector, c)
		if err := client.collectorRepository.Save(&newCollector); err != nil {
			color.Redln("RPC设置采集器失败: 保存采集器时发生错误, ERROR: %v", err)
			return 1, nil
		}
		color.Greenln("RPC设置采集器成功:", newCollector.Name)
	}

	// 删除不在新列表中的旧采集器（已禁用事件，不会停止采集任务，重启后生效）
	for _, existingCollector := range existingCollectors {
		if !newCollectorNames[existingCollector.Name] {
			if err := client.collectorRepository.Delete(existingCollector.Name); err != nil {
				zap.S().Warnf("删除采集器失败: %s, ERROR: %v", existingCollector.Name, err)
			} else {
				color.Yellowln("RPC清理采集器:", existingCollector.Name)
			}
		}
	}

	return 0, nil
}

func getCollectors(params map[string]interface{}, client Client) (int, interface{}) {
	all, err := client.collectorRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC获取采集器失败, ERROR: %v", err)
		return 1, nil
	}
	return 0, all
}

func getDeviceType(params map[string]interface{}, client Client) (int, interface{}) {
	all, err := client.deviceTypeRepository.FindAll()
	if err != nil {
		zap.S().Errorf("RPC获取设备类型失败, ERROR: %v", err)
		return 1, nil
	}
	result := make([]models.DeviceType, 0, len(all))
	for _, d := range all {
		add := models.DeviceType{
			Name:   d.Name,
			Driver: d.Driver,
		}
		util.ToolUtil.Copy(&add.Properties, d.Properties)
		result = append(result, add)
	}
	return 0, result
}

func reboot(params map[string]interface{}, client Client) (int, interface{}) {
	zap.S().Info("执行RPC命令reboot")

	io.SystemReboot()

	return 0, nil
}

func upgrade(params map[string]interface{}, client Client) (int, interface{}) {
	zap.S().Info("执行RPC命令upgrade")

	sourceFile, ok := params["url"].(string)
	if !ok {
		zap.S().Error("升级失败，缺少url参数")
		return 1, nil
	}

	fileName := "zsxagw.zip"
	if len(sourceFile) > 0 {
		io.Upgrade(sourceFile, io.GetCurrentPath()+fileName)
	}

	return 0, nil
}

func ping(params map[string]interface{}, client Client) (int, interface{}) {
	return 0, nil
}

func getLog(params map[string]interface{}, client Client) (int, interface{}) {
	// 获取主日志路径
	mainLogPath := io.GetLogPath()
	// 备用日志路径
	fallbackLogPath := "/www/wwwlogs/go/zsxagw.log"

	// 优先检查主路径
	logPath := mainLogPath
	if !io.PathExists(logPath) {
		// 主路径不存在时使用备用路径
		logPath = fallbackLogPath
		if !io.PathExists(logPath) {
			zap.S().Errorf("日志文件不存在，主路径:%s 备用路径:%s", mainLogPath, fallbackLogPath)
			return 1, nil
		}
	}

	content, err := io.ReadLastNLines(logPath, 100)
	if err != nil {
		zap.S().Errorf("读取日志文件失败: %v", err)
		return 1, nil
	}

	return 0, content
}

func healthCheck(params map[string]interface{}, client Client) (int, interface{}) {
	return 0, "OK"
}
